%%%-------------------------------------------------------------------
%%% File    : p19.erl
%%% Author  : Plamen Dragozov <plamen at dragozov.com>
%%% Description : 
%%% You are given the following information, but you may prefer to 
%%% do some research for yourself.
%%%
%%%    * 1 Jan 1900 was a Monday.
%%%    * Thirty days has September,
%%%      April, June and November.
%%%      All the rest have thirty-one,
%%%      Saving February alone,
%%%      Which has twenty-eight, rain or shine.
%%%      And on leap years, twenty-nine.
%%%    * A leap year occurs on any year evenly divisible by 4, but 
%%% not on a century unless it is divisible by 400.
%%%
%%% How many Sundays fell on the first of the month during the 
%%% twentieth century (1 Jan 1901 to 31 Dec 2000)?
%%%
%%%
%%% Created :  5 Dec 2008
%%%-------------------------------------------------------------------
-module(p19).

-compile(export_all).

%%====================================================================
%% API
%%====================================================================
%%--------------------------------------------------------------------
%% Function: solution(EndYear, EndMonth) -> int()
%% Description: Returns the number of Sundays that were 1st of the 
%% month between 1 Jan 1901 and last day of EndMonth, EndYear
%%--------------------------------------------------------------------
solution(EndYear, EndMonth) ->
    count(1901, 1, EndYear, EndMonth, 2, 0).%1st Jan 1901 was Tuesday

%%====================================================================
%% Internal functions
%%====================================================================
% Return the number of Sundays on 1st betweeb Year, Month and EndYear,
% EndMonth. 'Last' is which day was 1st in the previous month, 
% Sunday is 0, Monday is 1 etc.
%
count(Year, Month, EndYear, EndMonth, _, Acc) when (Year > EndYear) orelse (Year =:= EndYear andalso Month > EndMonth) ->
    Acc;
count(Year, Month, EndYear, EndMonth, Last, Acc) ->   
    Day = (Last + month_size(Year, Month)) rem 7,
    {NewYear, NewMonth} = case Month of 
                              12 -> {Year + 1, 1};
                              _ -> {Year, Month + 1}
                          end,
    count(NewYear, NewMonth, EndYear, EndMonth, Day, Acc + case Day of 
                                                               0 -> 1;
                                                               _ -> 0
                                                           end).

%Returns how many days in a month
month_size(Y, 2) when (Y rem 4 =:= 0) andalso ((Y rem 100 =/= 0) orelse (Y rem 400 =:= 0))->
    29;
month_size(_, 2) ->
    28;
month_size(_, 4) ->
    30;
month_size(_, 6) ->
    30;
month_size(_, 9) ->
    30;
month_size(_, 11) ->
    30;
month_size(_, _) ->
    31.



